package idcheck;
import java.util.*;
import java.io.*;
import java.time.*;
import java.time.format.*;

class 位数异常 extends Exception{}

class 非法字符异常 extends Exception{}

class 日期范围异常 extends Exception{}

class 校验码异常 extends Exception{}
class 地址信息异常 extends Exception{}
 public class IDCheck{

    String ID;
    private String 输入(){

        System.out.println("请输入身份证号码,退出请输入Q：");
        Scanner sc = new Scanner(System.in);
        ID = sc.nextLine();
        System.out.println("您输入的身份证号码为："+ID);

        return ID;

    }


     private String 位数转换(){
        String idf = ID.substring(0,6)+"19";
        String ide = ID.substring(6,15);
        ID = idf+ide;
        ID = ID+校验码(ID);
        System.out.println("您输入的身份证号是15位，转换后的身份证号为："+ID);
        return ID;
    }



    private boolean 出生日期校验()throws DateTimeParseException,日期范围异常{
        String date = ID.substring(6,14);
        String dateText = date.substring(0,4)+"-"+date.substring(4,6)+"-"+date.substring(6,8);
        LocalDate  lo = LocalDate.parse(dateText);
        Calendar c = Calendar.getInstance();
        String nowDate = String.format("%tY%tm%td",c,c,c);
        return (Integer.parseInt(date)<=Integer.parseInt(nowDate)&&Integer.parseInt(date.substring(0,4))>1900);

    }

    private boolean 校验码校验(){

        return (ID.substring(17,18).intern() == 校验码(ID).intern());

    }

    private String 校验码(String  IDCode){

        String s;
        int count = 0;
        int []num = new int[17];
        for (int i=0;i<17;i++)
        {
            num[i] = (IDCode.codePointAt(i)-48);
        }

        count = num[0]*7+num[1]*9+num[2]*10+num[3]*5+num[4]*8+num[5]*4+num[6]*2+num[7]*1+num[8]*6+num[9]*3+num[10]*7+num[11]*9+num[12]*10+num[13]*5+num[14]*8+num[15]*4+num[16]*2;
        //07－19－210－35－48－54－62－71－86－93－107－119－1210－135－148－154－162

        count = (count % 11);
        //余数只可能有0－1－2－3－4－5－6－7－8－9－10这11个数字。其分别对应的最后一位身份证的号码为
        //1－0－X－9－8－7－6－5－4－3－2

        switch(count){

            case 0: s = String.valueOf(1);
                break;
            case 1: s = String.valueOf(0);
                break;
            case 2: s = "X";
                break;
            case 3: s = String.valueOf(9);
                break;
            case 4: s = String.valueOf(8);
                break;
            case 5: s = String.valueOf(7);
                break;
            case 6: s = String.valueOf(6);
                break;
            case 7: s = String.valueOf(5);
                break;
            case 8: s = String.valueOf(4);
                break;
            case 9: s = String.valueOf(3);
                break;
            //case 10: return String.valueOf(2);
            //break;
            default: s = String.valueOf(2);

        }

        return s;
    }
     private boolean 地址信息校验() throws Exception{

         ArrayList<String> arr = new ArrayList<>();

         Scanner sc = new Scanner(new File("身份证号码地区码.txt")).useDelimiter("\\D+");

         while(sc.hasNext())
         {    arr.add(sc.next());}
         sc.close();

         return (arr.contains(ID.substring(0,6)));

     }
    public void 身份证校验(){



        while(true)
        {
            ID = 输入();
            ID.trim();
            if (ID.equalsIgnoreCase("q"))
                break;
            try{
                if ((ID.length()!=15)&&(ID.length()!=18))
                {throw new 位数异常();}

                if((!ID.matches("[0-9]{15}"))&&(!ID.matches("[0-9]{17}[0-9|x|X]{1}")))
                {throw new 非法字符异常();}

                if (ID.length()==15)            //先将15位全部转换为18位
                {ID = 位数转换();	}

                if (!地址信息校验())
                {throw new 地址信息异常();}

                if(!出生日期校验())
                {throw new 日期范围异常();}

                if (!校验码校验())
                {throw new 校验码异常();}
                System.out.println("您是位："+((((ID.codePointAt(16)-48)%2)>0)? "男士":"女士"));
                System.out.println("您的生日是："+ID.substring(6,10)+"年"+ID.substring(10,12)+"月"+ID.substring(12,14)+"日");
            }

            catch (位数异常 e){System.out.println("您输入的身份证号码位数有误，请重新输入！");}

            catch (非法字符异常 e){System.out.println("您输入的身份证号码含有非数字字符，请重新输入！");}

            catch (地址信息异常 e){System.out.println("您输入的身份证号码省市地址信息有误，请重新输入！");}

            catch(DateTimeParseException e){System.out.println("出生日期错误");}

            catch (日期范围异常 e){System.out.println("您输入的身份证号码出生日期范围有误，请重新输入！");}

            catch (校验码异常 e){System.out.println("您输入的身份证号码非法，校验码错误，请重新输入！");}

            catch(Exception e){e.getMessage();}

        }

        System.out.println("您已经成功退出！");


    }
}


